/*
 * EvolutionPartnerSelection.java
 *
 * Created on 31 de Agosto de 2010, 18:01
 *
 */

package intopo.evogame.partnerselection;


import intopo.evogame.partnerselection.chromosome.Chromosome;
import intopo.evogame.partnerselection.config.AbstractTextConfigFile;
import intopo.evogame.partnerselection.config.ParsingException;
import intopo.evogame.partnerselection.player.AbstractPlayer;
import intopo.evogame.partnerselection.population.GeographicPopulation;
import intopo.game.Game;
import intopo.game.Strategy;

import java.io.PrintStream;
import java.util.Scanner;

/**
 *
 * @author <a href="mailto:mariano.pedro@gmail.com">Pedro Lopes da Silva Mariano</a>
 *
 * @version 1.0 31 de Agosto de 2010
 */
public class EvolutionaryAlgorithm<
	G extends Game<S>,
	S extends Strategy<S>,
	C extends Chromosome<S>,
	P extends AbstractPlayer<S, C, P>>
{
	/**
	 * Game that is going to be played by the players in the population.
	 */
	final G game;
	
	/**
	 * Population of players in the current round.
	 */
	final GeographicPopulation<S, C, P> population;

	/**
	 * Used internally to store the strategies that are going to play a game.
	 */
	transient Game.Strategies<S> strategies;

	transient AbstractPlayer[] players;

	/**
	 * Creates a new instance of EvolutionPartnerSelection
	 */
	public EvolutionaryAlgorithm (G game, GeographicPopulation<S, C, P> population)
	{
		this.game = game;
		this.population = population;
		strategies = new Game.Strategies<S> (game.numberPlayers ());
		players = new AbstractPlayer [game.numberPlayers ()];
	}
	public void run ()
	{
		try {
			int round = 0;
			while (round < Parameters.numberRounds) {
				for (P p : population.getPlayers ()) {
					p.playGame (round, this.game, this.strategies, this.players);
				}
				round++;
				this.population.nextGeneration (round);
//				this.debug (round);
			}
		}
		catch (java.io.IOException e) {
			System.err.println ("Error writing data to files");
			System.exit (1);
		}
	}
	void debug (int time)
	{
		System.out.format ("\n* ** *** Round %d *** ** *\n", time);
		this.population.debug ();
	}
	static public class Parameters
	{
		static public int numberRounds = 2;
		static public void read (Scanner scanner)
			throws ParsingException
		{
			numberRounds = AbstractTextConfigFile.readInt (scanner, "number of rounds");
		}
		static public void write (PrintStream ps)
		{
			ps.print (Parameters.numberRounds);
			ps.println ("\t# number of rounds");
		}
	}
}
